Skip to content

Go SDK: OTLP logs signal (ADR-100) - #72

Merged
brentrager merged 2 commits into
mainfrom
feat/go-otlp-logs-signal
Aug 11, 2026
Merged

Go SDK: OTLP logs signal (ADR-100)#72
brentrager merged 2 commits into
mainfrom
feat/go-otlp-logs-signal

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

The Go observability SDK exported traces and metrics but no logs. ADR-100 adds a logs signal into the product /v1/logs OTLP endpoint, correlated to traces.

Solution

Adds the third OTLP pipeline, reusing the existing traces/metrics wiring verbatim:

  • go/logs.gobuildLoggerProvider (sdk/log LoggerProvider + BatchProcessor + otlploghttp exporter) and SlogHandler(name) (an otelslog bridge over the global LoggerProvider).
  • go/otel.goSetupOtelOptions.LogsEndpoint, OtelSDKHandle.LoggerProvider, logs block in SetupOtelSDK, global registration via log/global.SetLoggerProvider, and Flush/Shutdown coverage.
  • go/bootstrap.go — resolves /v1/logs off the same SMOOAI_OBSERVABILITY_ENDPOINT base and the OTEL_EXPORTER_OTLP_LOGS_ENDPOINT fallback.

Same endpoint base, same auth (static header or TokenProvider via buildHTTPClient), same resource, same enable/init gating. No new config keys. Graceful no-op when no logs endpoint is configured (nil provider; the SlogHandler drops records against the no-op global provider).

Column mapping

severity←level, body←message, trace_id/span_id←active span context (the otelslog bridge reads it from ctx), resource service.nameservice_name, attrs→parsed_fields.

Deps (pinned to otel core v1.44.0, no unrelated bumps)

otel/log + sdk/log + otlploghttp v0.20.0, contrib/bridges/otelslog v0.19.0.

Tests

go test ./...55 passed (3 new). Correlation verified by round-trip, not just compiled: TestSlogHandlerCorrelatesWithActiveSpan starts a real span, logs through SlogHandler, and asserts the exported sdklog.Record.TraceID()/SpanID() equal the span's ids. Plus no-span (zero ids) and no-endpoint no-op cases. go vet clean, gofmt clean.

🤖 Generated with Claude Code

Adds the third OTLP pipeline alongside traces and metrics: an sdk/log
LoggerProvider with a batch processor exporting to the product /v1/logs
endpoint, plus an otelslog-backed slog.Handler (SlogHandler) so app logs
become OTel log records correlated to the active span.

Reuses the existing traces/metrics wiring verbatim — same
SMOOAI_OBSERVABILITY_ENDPOINT base (logs → /v1/logs), same auth
(static header or TokenProvider via buildHTTPClient), same resource, same
enable/init gating. Graceful no-op when no logs endpoint is configured.

Deps pinned to otel core v1.44.0: otel/log + sdk/log + otlploghttp
v0.20.0, otelslog v0.19.0. No unrelated bumps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S2bM94GAnVjYSSv1x7HKRB
@changeset-bot

changeset-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 0373847

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

CI's `go` job failed in the submodule vet groups, not the root:

    ../logs.go:7:2: missing go.sum entry for module providing package
    go.opentelemetry.io/contrib/bridges/otelslog

`go/fiber` and `go/gin` are separate modules that `replace` the parent, so the
new logs dependencies need entries in their OWN go.sum. `go mod tidy` in all
three. Vet is clean across root, fiber and gin.

Two assertions in this PR could not fail, so the feature they cover had no
coverage at all:

- logs_test.go: `if r.Severity() != 0 && r.Severity() < 1` demands an integer
  strictly between 0 and 1. Never true, so the slog level mapping was untested.
  Now asserts `log.SeverityWarn`, matching the `WarnContext` call that emitted
  the line. Verified live: expecting SeverityError instead fails with
  `severity = WARN, want ERROR`, where before nothing could fail.

- otel_test.go: the no-endpoint check asserted TracerProvider and MeterProvider
  were nil but not LoggerProvider — the one this PR adds. Widened.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@brentrager
brentrager merged commit 1ceb664 into main Aug 11, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant